
<script setup lang="ts">
import { ref, watch, onMounted } from 'vue';
import { getImgUrl } from "#/utils/getImgUrl"

const props = defineProps({
  src: { type: String, required: true },  // 图片地址（可异步拼接）
  alt: { type: String, default: '' },     // alt 文本
  imgStyle: { type: Object, default: () => ({}) }, // 自定义样式
});

const emit = defineEmits(['imageLoaded'])

const status = ref('loading'); // loading | loaded | error
const refSrc = ref()
// 图片加载逻辑
async function loadImage(path:any) {
  const src = await getImgUrl(path) as any
  const base64Content = arrayBufferToImageBase64(src)
  refSrc.value = base64Content
  status.value = 'loading'
  const img = new Image() as any
  img.src = base64Content
  img.crossorigin = 'anonymous'
  img.onload = () => {
    emit('imageLoaded')
    status.value = 'loaded'
  };
  img.onerror = () => {
    status.value = 'error'
  };
}

function arrayBufferToImageBase64(buffer: ArrayBuffer, mimeType: string = 'image/png'): string {
  const bytes = new Uint8Array(buffer)
  let binary = '';
  bytes.forEach(byte => binary += String.fromCharCode(byte))
  return `data:${mimeType};base64,${btoa(binary)}`
}


// 手动触发错误处理（如网络问题）
function handleError() {
  status.value = 'error';
}

// 监听 src 变化（适用于动态拼接的 URL）
watch(() => props.src, (newSrc) => {
  loadImage(newSrc);
});

// 初始化加载
onMounted(() => {
  loadImage(props.src);
});
</script>
<template>
  <div class="async-image">
    <!-- 加载中状态 -->
    <div v-if="status === 'loading'" class="placeholder">
      <slot name="loading">Loading...</slot>
    </div>
    
    <!-- 加载成功 -->
    <img
      v-else-if="status === 'loaded'"
      :src="refSrc"
      :alt="alt"
      style="page-break-inside: avoid;break-inside: avoid; "
      class="image-img"
      :style="imgStyle"
      @error="handleError"
    />
    
    <!-- 加载失败 -->
    <div v-else class="error">
      <slot name="error" @click="loadImage(src)">Failed to load image</slot>
    </div>
  </div>
</template>


<style scoped>
.async-image {
  position: relative;
}
.placeholder, .error {
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f5f5f5;
  color: #888;
}
img {
  max-width: 100%;
  height: auto;
  display: block;
}
.image-img {
  page-break-inside: avoid; /* 旧浏览器兼容 */
  break-inside: avoid;     /* 现代浏览器标准 */
  display: block;
  overflow: hidden;
}
</style>
